﻿using System.Linq;
using System.Linq.Expressions;
using System;
using DotNetCommon;
using DotNetCommon.Extensions;
using System.Collections.Generic;
using System.Diagnostics;

namespace DotNetCommon.ReduceLambdaPerformance
{
    internal class Program
    {
        static void Main(string[] args)
        {
            object lambda = null;
            var st = new Stopwatch();
            st.Restart();
            lambda = ExpressionHelper.ReduceLambda(GetExpression());
            st.Stop();
            Console.WriteLine($"预热耗时: {st.ElapsedMilliseconds} 毫秒");

            st.Restart();
            for (int i = 0; i < 1000; i++)
            {
                lambda = ExpressionHelper.ReduceLambda(GetExpression());
            }
            st.Stop();
            Console.WriteLine($"1千次耗时: {st.ElapsedMilliseconds} 毫秒，平均: {st.ElapsedMilliseconds / (1000 * 1.0)} 毫秒");

            st.Restart();
            for (int i = 0; i < 10000; i++)
            {
                lambda = ExpressionHelper.ReduceLambda(GetExpression());
            }
            st.Stop();
            Console.WriteLine($"1万次耗时: {st.ElapsedMilliseconds} 毫秒，平均: {st.ElapsedMilliseconds / (10000 * 1.0)} 毫秒");

            st.Restart();
            for (int i = 0; i < 10000 * 10; i++)
            {
                lambda = ExpressionHelper.ReduceLambda(GetExpression());
            }
            st.Stop();
            Console.WriteLine($"10万次耗时: {st.ElapsedMilliseconds} 毫秒，平均: {st.ElapsedMilliseconds / (10000 * 10 * 1.0)} 毫秒");


            Console.WriteLine("Hello, World!");
        }

        private static Expression<Func<Person, bool>> GetExpression()
        {
            var list = new List<Person>
            {
                new Person{Id=1,Name="刘备",Age=40},
                new Person{Id=2,Name="关羽",Age=38},
                new Person{Id=3,Name="张飞",Age=36}
            };
            return p => p.Id < 100
                & list.Select(i => i.Id).Contains(p.Id)
                & p.Name.StartsWith(list.FirstOrDefault(i => i.Age >= 40).Name.SplitAndTrim("").FirstOrDefault())
                & p.Age >= list.GroupBy(i => i.Id).FirstOrDefault().ToList().FirstOrDefault().Age
                & p.Name.IsNotNullOrEmpty()
                & p.Age <= 100
                & p.Birth > DateTime.Now.AddYears(-200)
                & p.Birth < DateTime.Now;
        }
    }

    public class Person
    {
        public int Id { get; set; }
        public int Age { get; set; }
        public DateTime? Birth { get; set; }
        public string Name { get; set; }
        public int? Score { get; set; }
    }
}